package com.example.demojpa.aop;

import cn.hutool.log.Log;
import com.example.demojpa.config.MyLog;
import org.aopalliance.intercept.Joinpoint;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Map;

@Aspect
@Component
public class LogAspect {
    /**
     * 此处定义切点是注解方法,这里使用注解的方式。
     * 也可以使用aop最原始的支撑包名的方式
     */
    @Pointcut("@annotation(com.example.demojpa.config.MyLog)")
    public void myLog(){};

    /*环绕增强*/
    @Around("myLog()")
    public Object doAroud(ProceedingJoinPoint joinPoint) throws Throwable {
        Object res=null;
        long time = System.currentTimeMillis();

        try {
            //方法继续执行
            res=joinPoint.proceed();
            time=System.currentTimeMillis()-time;
            return res;
        }finally {
            try {
                addOperationLog(joinPoint,res,time);
            }catch (Exception e){
                System.out.println("LogAspect 操作失败：" + e.getMessage());
                e.printStackTrace();
            }
        }
    }

    private void addOperationLog(JoinPoint joinPoint, Object res, long time){
        //joinPoint.getSignature()获取封装了署名的对象，在该对象中可以获取目标方法名，
        //所属类的class等信息
        MethodSignature signature = (MethodSignature)joinPoint.getSignature();
        String method = signature.getDeclaringTypeName() + "." + signature.getName();
        System.out.println("拦截方法名："+method);
        //获取注解对象，取到注解里定义的字段
        MyLog annotation = signature.getMethod().getAnnotation(MyLog.class);
        if(annotation != null) {

            String title = annotation.title();
            String metho = annotation.method();
            String operateType = annotation.operate();
            boolean isSaveData = annotation.isSaveData();
            System.out.println("title:"+title+",bizType:"+metho+",operateType:"+operateType+",isSaveData:"+isSaveData);
            //获取参数
            HttpServletRequest request = ((ServletRequestAttributes)(RequestContextHolder.getRequestAttributes())).getRequest();
            Map<String, String[]> map =request.getParameterMap();
            if (map == null || map.isEmpty()) {
                return;
            }
            //输出参数
            for(String key : map.keySet()){
                System.out.println("key:"+key+",value="+map.get(key));
            }
        }
        //TODO 这里保存日志
        System.out.println("记录日志:");
    }
}
